package com.rent.common.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.rent.common.constant.CommonConstant;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT工具类
 * 用于生成和验证JWT Token
 * 基于auth0的java-jwt库
 */
@Slf4j
public class JwtUtil {
    
    /**
     * 生成Token
     * 
     * @param userId 用户ID
     * @param username 用户名
     * @param role 用户角色
     * @return Token字符串
     */
    public static String generateToken(Long userId, String username, Integer role) {
        try {
            // 过期时间
            Date expireDate = new Date(System.currentTimeMillis() + CommonConstant.JWT_EXPIRE_TIME);
            
            // 加密算法
            Algorithm algorithm = Algorithm.HMAC256(CommonConstant.JWT_SECRET);
            
            // 设置头部信息
            Map<String, Object> header = new HashMap<>();
            header.put("typ", "JWT");
            header.put("alg", "HS256");
            
            // 生成Token
            String token = JWT.create()
                    .withHeader(header)
                    .withClaim("userId", userId)
                    .withClaim("username", username)
                    .withClaim("role", role)
                    .withExpiresAt(expireDate)
                    .sign(algorithm);
            
            log.debug("生成Token成功，userId: {}, username: {}", userId, username);
            return token;
        } catch (Exception e) {
            log.error("生成Token失败", e);
            return null;
        }
    }
    
    /**
     * 验证Token是否有效
     * 
     * @param token Token字符串
     * @return true-有效，false-无效
     */
    public static boolean verify(String token) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(CommonConstant.JWT_SECRET);
            JWTVerifier verifier = JWT.require(algorithm).build();
            verifier.verify(token);
            return true;
        } catch (Exception e) {
            log.debug("Token验证失败：{}", e.getMessage());
            return false;
        }
    }
    
    /**
     * 解析Token，获取用户ID
     * 
     * @param token Token字符串
     * @return 用户ID
     */
    public static Long getUserId(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("userId").asLong();
        } catch (Exception e) {
            log.error("解析Token失败", e);
            return null;
        }
    }
    
    /**
     * 解析Token，获取用户名
     * 
     * @param token Token字符串
     * @return 用户名
     */
    public static String getUsername(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("username").asString();
        } catch (Exception e) {
            log.error("解析Token失败", e);
            return null;
        }
    }
    
    /**
     * 解析Token，获取用户角色
     * 
     * @param token Token字符串
     * @return 用户角色
     */
    public static Integer getRole(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("role").asInt();
        } catch (Exception e) {
            log.error("解析Token失败", e);
            return null;
        }
    }
    
    /**
     * 解析Token，获取所有信息
     * 
     * @param token Token字符串
     * @return 包含用户信息的Map
     */
    public static Map<String, Object> parseToken(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            Map<String, Claim> claims = jwt.getClaims();
            
            Map<String, Object> result = new HashMap<>();
            result.put("userId", claims.get("userId").asLong());
            result.put("username", claims.get("username").asString());
            result.put("role", claims.get("role").asInt());
            
            return result;
        } catch (Exception e) {
            log.error("解析Token失败", e);
            return null;
        }
    }
    
    /**
     * 判断Token是否过期
     * 
     * @param token Token字符串
     * @return true-已过期，false-未过期
     */
    public static boolean isExpired(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            Date expiresAt = jwt.getExpiresAt();
            return expiresAt.before(new Date());
        } catch (Exception e) {
            log.error("判断Token过期失败", e);
            return true;
        }
    }
}

